#include <pcap.h>
#include "vars.h"

extern int size_transport, show_payload; /* packet counter */
extern float nip, ntcp, nudp;

int print_udp_header(sniff_udp *udp);
int print_tcp_header(sniff_tcp *tcp);
void print_payload(const u_char *payload, int len);

void
manage_tcp_header(const u_char *packet, int size_ip) {
    struct sniff_tcp *tcp; /* The TCP header */
    tcp = (struct sniff_tcp*) (packet + SIZE_ETHERNET + size_ip);
    if ((size_transport = print_tcp_header(tcp)) == -1)
        return;
    ntcp++;
}

void
manage_udp_header(const u_char *packet, int size_ip) {
    struct sniff_udp *udp; /* The UDP header */
    udp = (struct sniff_udp*) (packet + SIZE_ETHERNET + size_ip);
    if ((size_transport = print_udp_header(udp)) == -1)
        return;
    nudp++;
}

void
manage_ip_header(const u_char *packet) {
    const struct sniff_ip *ip; /* The IP header */
    const u_char *payload; /* Packet payload */
    int size_ip, size_payload;

    /* define/compute ip header offset                                                  */
    /*                  V                                                               */
    /*                  V                                                               */
    /*                  V                                                               */
    /************************************************************************************/
    /* 	ETHERNET	|	IP	|	TCP/UDP		|	PAYLOAD		*/
    /************************************************************************************/
    ip = (struct sniff_ip*) (packet + SIZE_ETHERNET);
    size_ip = IP_HL(ip)*4;
    if (size_ip < 20) {
        printf("\t* Invalid IP header length: %u bytes\n", size_ip);
        return;
    }
    nip++;

    /* print source and destination IP addresses */
    printf("\tFrom: %s\n", inet_ntoa(ip->ip_src));
    printf("\tTo: %s\n", inet_ntoa(ip->ip_dst));

    /* determine protocol */
    switch (ip->ip_p) {
        case IPPROTO_TCP:
            printf("\tProtocol: TCP\n");
            manage_tcp_header(packet, size_ip);
            break;
        case IPPROTO_UDP:
            printf("\tProtocol: UDP\n");
            manage_udp_header(packet, size_ip);
            break;
        default:
            printf("\tProtocol: unknown = %i\n", ip->ip_p);
            return;
    }

    if (size_transport == -1)
        return;

    /* define/compute tcp payload (segment) offset */
    payload = (u_char *) (packet + SIZE_ETHERNET + size_ip + (size_transport));

    /* compute tcp payload (segment) size */
    size_payload = ntohs(ip->ip_len) - (size_ip + size_transport);

    /*
     * Print payload data; it might be binary, so don't just
     * treat it as a string.
     */
    if (size_payload > 0 && show_payload != 0) {
        printf("\tPayload (%d bytes):\n", size_payload);
        print_payload(payload, size_payload);
    }
}
